/*	Copyright
 
 This file falls within the license domain specified in "IAGraphics.h"
 */


#import "CGImageAdjunct.h"




CGImageRef	CGImageCreateWithDrawingBlock	( CGSize size , void(^draw)(CGContextRef) ) {
	size.width	=	floor ( size.width ) ;
	size.height	=	floor ( size.height ) ;
	
	UInt32	mNBytesPerRow		=	size.width * sizeof(UInt32) ;
	UInt32	mNBytesPerComponent	=	sizeof(UInt8) ;
	UInt32	mNBitsPerComponent	=	mNBytesPerComponent * 8 ;
	UInt32	mBitmapInfo			=	kCGImageAlphaPremultipliedLast ; //| kCGBitmapByteOrder32Big ;
	
	UInt32	mDefault			=	0x00000000 ;
	//								__AABBGGRR
	
	NSUInteger	count			=	size.width*size.height ;
	
	UInt32	* mpData = malloc ( sizeof(UInt32) * count ) ;
	
	// Zero the data
	{
	UInt32	*	here	=	mpData ;
	UInt32	*	end		=	here + count ;
	while ( here < end )
		*(here++)		=	mDefault ;
	}
	
	//memset ( (void*)mpData , 255 , count*4 ) ;
	
	CGColorSpaceRef		colorSpace		= CGColorSpaceCreateDeviceRGB ();
	CGContextRef		context			= CGBitmapContextCreate ( mpData , size.width , size.height , mNBitsPerComponent , mNBytesPerRow , colorSpace , mBitmapInfo ) ;
	
	if ( context == nil )
		[NSException raise:NSGenericException format:@"Tried to create bitmap CGContext, but failed"] ;
	
	CGContextSetStrokeColorSpace	( context , colorSpace ) ;
	CGContextSetFillColorSpace		( context , colorSpace ) ;
	
	// This actually, finally does the transfer of the image data into mpData;
	draw ( context ) ;
	
	
	// Make sure we DREW something
	{
	UInt32	*	here	=	mpData ;
	UInt32	*	end		=	here + count ;
	while ( here < end )
		{
		UInt32	it	=	*(here++) ;
		if ( mDefault != it )
			break ;
		}
	if ( here == end )
		NSLog ( @"*** Warning: CGImageCreateWithDrawingBlock called, but block didn't write to context ***" ) ;
	}
	
	
	// Create the image
	
	CGImageRef	image	=	CGBitmapContextCreateImage(context) ;
	
	if ( image == nil )
		[NSException raise:NSGenericException format:@"Tried to image from create bitmap CGContext, but failed"] ;
	
	CGContextRelease		( context ) ;
	CGColorSpaceRelease		( colorSpace ) ;
	free ( (void*) mpData ) ;
	
	return image ;
}















#pragma mark	-	Device-Specific Writers
#pragma mark		iOS

#ifdef __IPHONE_OS_VERSION_MIN_REQUIRED

#import <UIKit/UIKit.h>


void	CGImageWriteToFile		( CGImageRef inImage , NSString * inFile ) {
	UIImage * image = [UIImage imageWithCGImage:inImage] ;
	NSData * data = UIImagePNGRepresentation ( image ) ;
	[data writeToFile:inFile atomically:YES] ;
}
void	CGImageWritePNGToFile	( CGImageRef inImage , NSString * inFile ) {
	UIImage * image = [UIImage imageWithCGImage:inImage] ;
	NSData * data = UIImagePNGRepresentation ( image ) ;
	[data writeToFile:inFile atomically:YES] ;
}
void	CGImageWriteJPGToFile	( CGImageRef inImage , NSString * inFile ) {
	UIImage * image = [UIImage imageWithCGImage:inImage] ;
	NSData * data = UIImageJPEGRepresentation ( image , 0.9 ) ;
	[data writeToFile:inFile atomically:YES] ;
}

CGImageRef	CGImageCreateWithFile			( NSString * inFile ) {
	UIImage * image = [UIImage imageWithContentsOfFile:inFile] ;
	return (CGImageRef) CFRetain ( image.CGImage ) ;
}
CGImageRef	CGImageCreateWithPNGFile		( NSString * inFile ) {
	UIImage * image = [UIImage imageWithContentsOfFile:inFile] ;
	return (CGImageRef) CFRetain ( image.CGImage ) ;
}
CGImageRef	CGImageCreateWithJPGFile		( NSString * inFile ) {
	UIImage * image = [UIImage imageWithContentsOfFile:inFile] ;
	return (CGImageRef) CFRetain ( image.CGImage ) ;
}



#pragma mark		OS X

#else

#import <Quartz/Quartz.h>
#import <ApplicationServices/ApplicationServices.h> // Required for SL


void	CGImageWriteToFile		( CGImageRef inImage , NSString * inFile ) {
	NSString * suffix = [inFile pathExtension] ;
	
	if ( [suffix caseInsensitiveCompare:@"png"] == NSOrderedSame )
		{
		CGImageWritePNGToFile ( inImage , inFile ) ;
		}
	else if ( [suffix caseInsensitiveCompare:@"jpg"] == NSOrderedSame )
		{
		CGImageWriteJPGToFile ( inImage , inFile ) ;
		}
}
void	CGImageWritePNGToFile	( CGImageRef inImage , NSString * inFile ) {
	if ( inImage == NULL )
		{
		NSLog ( @"Warning: Cannot write. inImage is NULL" ) ;
		return ;
		}
	if ( inFile == NULL )
		{
		NSLog ( @"Warning: Cannot write. inPath is NULL" ) ;
		return ;
		}
	
	CFMutableDataRef data = CFDataCreateMutable ( kCFAllocatorDefault , 0 ) ;
	
	CGImageDestinationRef destination = CGImageDestinationCreateWithData ( data , kUTTypePNG , 1 , NULL ) ;
	CGImageDestinationAddImage ( destination , inImage , NULL ) ;
	CGImageDestinationFinalize(destination) ;
	CFRelease(destination) ;
	
	[  (NSData*)(objc_unretainedObject(data))  writeToFile:inFile atomically:YES  ] ;
	
	CFRelease ( data ) ;
}
void	CGImageWriteJPGToFile	( CGImageRef inImage , NSString * inFile ) {
	if ( inImage == NULL )
		{
		NSLog ( @"Warning: Cannot write. inImage is NULL" ) ;
		return ;
		}
	if ( inFile == NULL )
		{
		NSLog ( @"Warning: Cannot write. inPath is NULL" ) ;
		return ;
		}
	
	CFMutableDataRef data = CFDataCreateMutable ( kCFAllocatorDefault , 0 ) ;
	
	CGImageDestinationRef destination = CGImageDestinationCreateWithData ( data , kUTTypeJPEG , 1 , NULL ) ;
	CGImageDestinationAddImage ( destination , inImage , NULL ) ;
	CGImageDestinationFinalize(destination) ;
	CFRelease(destination) ;
	
	[  (NSData*)(objc_unretainedObject(data))  writeToFile:inFile atomically:YES  ] ;
	
	CFRelease ( data ) ;
}

CGImageRef	CGImageCreateWithFile			( NSString * path ) {
	NSString * suffix = [path pathExtension] ;
	
	if ( [suffix caseInsensitiveCompare:@"png"] == NSOrderedSame )
		{
		return CGImageCreateWithPNGFile ( path ) ;
		}
	else if ( [suffix caseInsensitiveCompare:@"jpg"] == NSOrderedSame )
		{
		return CGImageCreateWithJPGFile ( path ) ;
		}
	
	return 0 ;
}
CGImageRef	CGImageCreateWithPNGFile		( NSString * inFile ) {
	CGImageRef outImage = nil ;
	
	if ( inFile == NULL )
		{
		NSLog ( @"Warning: Cannot read. inPath is NULL" ) ;
		return nil ;
		}
	
	const char * str = [ inFile cStringUsingEncoding:NSASCIIStringEncoding ] ;
	
	CGDataProviderRef dataProvider = CGDataProviderCreateWithFilename(str) ;
	
	if ( dataProvider == NULL ) NSLog ( @"Warning: dataProvider is NULL" ) ;
	
	outImage = CGImageCreateWithPNGDataProvider(dataProvider, NULL, NO, kCGRenderingIntentDefault) ;
	
	CGDataProviderRelease(dataProvider) ;
	
	return outImage ;
}
CGImageRef	CGImageCreateWithJPGFile		( NSString * inFile ) {
	CGImageRef outImage = nil ;
	
	if ( inFile == NULL )
		{
		NSLog ( @"Warning: Cannot read. inPath is NULL" ) ;
		return nil ;
		}
	
	const char * str = [ inFile cStringUsingEncoding:NSASCIIStringEncoding ] ;
	
	CGDataProviderRef dataProvider = CGDataProviderCreateWithFilename(str) ;
	
	if ( dataProvider == NULL ) NSLog ( @"Warning: dataProvider is NULL" ) ;
	
	outImage = CGImageCreateWithJPEGDataProvider(dataProvider, NULL, NO, kCGRenderingIntentDefault) ;
	
	CGDataProviderRelease(dataProvider) ;
	
	return outImage ;
}



#endif